/*
 * @(#)WorkflowStepManager.java
 *
 * Copyright (c) 2003 DCIVision Ltd
 * All rights reserved.
 *
 * This software is the confidential and proprietary information of DCIVision
 * Ltd ("Confidential Information").  You shall not disclose such Confidential
 * Information and shall use it only in accordance with the terms of the license
 * agreement you entered into with DCIVision Ltd.
 */
package com.dcivision.workflow.core;

import java.sql.Connection;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import com.dcivision.framework.ApplicationException;
import com.dcivision.framework.ErrorConstant;
import com.dcivision.framework.MessageResourcesFactory;
import com.dcivision.framework.SessionContainer;
import com.dcivision.framework.TextUtility;
import com.dcivision.framework.Utility;
import com.dcivision.workflow.bean.MtmWfStepFormRecord;
import com.dcivision.workflow.bean.MtmWfStepNotificationRule;
import com.dcivision.workflow.bean.MtmWfStepNotificationTarget;
import com.dcivision.workflow.bean.MtmWorkflowInterruptUserActor;
import com.dcivision.workflow.bean.MtmWorkflowRecordObjectLink;
import com.dcivision.workflow.bean.MtmWorkflowStepPriorityRule;
import com.dcivision.workflow.bean.MtmWorkflowStepUserActor;
import com.dcivision.workflow.bean.MtmWorkflowStepWorkflowStep;
import com.dcivision.workflow.bean.WorkflowAction;
import com.dcivision.workflow.bean.WorkflowStep;
import com.dcivision.workflow.bean.WorkflowStepFormEquat;
import com.dcivision.workflow.bean.WorkflowStepParameterValue;
import com.dcivision.workflow.bean.WorkflowStepRoute;
import com.dcivision.workflow.dao.MtmWfStepFormRecordDAObject;
import com.dcivision.workflow.dao.MtmWfStepNotificationRuleDAObject;
import com.dcivision.workflow.dao.MtmWfStepNotificationTargetDAObject;
import com.dcivision.workflow.dao.MtmWorkflowInterruptUserActorDAObject;
import com.dcivision.workflow.dao.MtmWorkflowRecordObjectLinkDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepPriorityRuleDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepUserActorDAObject;
import com.dcivision.workflow.dao.MtmWorkflowStepWorkflowStepDAObject;
import com.dcivision.workflow.dao.WorkflowActionDAObject;
import com.dcivision.workflow.dao.WorkflowRecordDAObject;
import com.dcivision.workflow.dao.WorkflowStepDAObject;
import com.dcivision.workflow.dao.WorkflowStepFormEquatDAObject;
import com.dcivision.workflow.dao.WorkflowStepParameterValueDAObject;
import com.dcivision.workflow.dao.WorkflowStepRouteDAObject;

/**
 * WorkflowStepManager.java
 *
 * This class is responsible for workflow operation.
 *
 * @author Rollo Chan
 * @company DCIVision Limited
 * @creation date 06/10/2003
 * @version $Revision: 1.16 $
*/

public class WorkflowStepManager {

  public static final String REVISION = "$Revision: 1.16 $";


  private SessionContainer sessionCon = null;
  private Connection dbConn = null;

  /**
   * Constructor
   *
   * @param sessionContainer
   * @param conn
   */
  public WorkflowStepManager(SessionContainer sessionContainer, Connection conn) {
    this.sessionCon = sessionContainer;
    this.dbConn = conn;
  }

  /**
   * Gets the workflow step relationships by the given workflow record.
   *
   * @param workflowRecordID       Workflow record ID.
   * @return                       The list with all workflow step relationships.
   * @throws ApplicationException
   * @see com.dcivision.workflow.bean.WorkflowRecord
   * @see com.dcivision.workflow.bean.WorkflowStep
   */
  public List getWorkflowStepRelationshipList(Integer workflowRecordID) throws ApplicationException {
    MtmWorkflowStepWorkflowStepDAObject mtmStepDAO = new MtmWorkflowStepWorkflowStepDAObject(sessionCon, dbConn);
    List workflowStepList = mtmStepDAO.getListByWorkflowID(workflowRecordID);
    //get the step relationships order by the displayed tree map,to fix the bug that the tree displayed abnormally
    List sortWorkflowStepList = getSortWorkflowStepList(workflowStepList);
    return sortWorkflowStepList;
  }

  /**
   * Gets the workflow steps with the actor list by the given workflow record.
   *
   * @param workflowRecordID       Workflow record ID.
   * @return                       The list with all workflow step relationships.
   * @throws ApplicationException
   * @see com.dcivision.workflow.bean.WorkflowRecord
   * @see com.dcivision.workflow.bean.WorkflowStep
   * @see com.dcivision.workflow.bean.MtmWorkflowStepUserActor
   */
  public List getWorkflowStepWithActorList(Integer workflowRecordID) throws ApplicationException {
    //WorkflowStepDAObject stepDAO = new WorkflowStepDAObject(sessionCon, dbConn);
    //List workflowStepList = stepDAO.getListByWorkflowRecordID(workflowRecordID);
    WorkflowRetrievalManager retrievalManager = new WorkflowRetrievalManager(sessionCon, dbConn);
    List workflowStepList = retrievalManager.getWorkflowStepListByRecordID(workflowRecordID);

    List afterInit = new ArrayList(workflowStepList.size());

    MtmWorkflowStepUserActorDAObject mtmUserActorDAO = new MtmWorkflowStepUserActorDAObject(sessionCon, dbConn);
    for (Iterator iterator = workflowStepList.iterator(); iterator.hasNext();) {
      WorkflowStep workflowStep = (WorkflowStep)iterator.next();
      workflowStep.setUserActorList(mtmUserActorDAO.getListByWorkflowStepID(workflowStep.getID()));
      afterInit.add(workflowStep);
    }
    return afterInit;
  }
  /**
   * Sorts the given workflow step relationship list
   *
   * @param workflowStepList       The workflow step relationships list.
   * @return                       The workflow step relationships list order by workflow chart.
   * @throws ApplicationException
   * @see com.dcivision.workflow.bean.MtmWorkflowStepWorkflowStep
   */
  public List getSortWorkflowStepList(List workflowStepList){
      if ( Utility.isEmpty(workflowStepList) ) return workflowStepList;

      List sortWorkflowStepList=new ArrayList();
      MtmWorkflowStepWorkflowStep rootStepStep = (MtmWorkflowStepWorkflowStep)workflowStepList.get(0);
      insertStepRelation(workflowStepList,sortWorkflowStepList,rootStepStep.getParentStepID());
      /*sortWorkflowStepList.add(workflowStepList.get(0));
      MtmWorkflowStepWorkflowStep insertStepStep = (MtmWorkflowStepWorkflowStep)workflowStepList.get(0);
      for (int i=1;i<workflowStepList.size();i++){
          for (int j=1;j<workflowStepList.size();j++)
          {
              MtmWorkflowStepWorkflowStep tempStepStep = (MtmWorkflowStepWorkflowStep)workflowStepList.get(j);
              if (tempStepStep.getParentStepID().equals(insertStepStep.getChildStepID())){
                  sortWorkflowStepList.add(tempStepStep);
                  insertStepStep = tempStepStep;
              }
          }
      }*/
      return sortWorkflowStepList;
  }

  /**
   * Adds step relationships to sortWorkflowStepList.
   *
   * @param workflowStepList       The workflow step relationships list.
   * @param sortWorkflowStepList       The sorted workflow step relationships list.
   * @param rootID  The workflow step root ID
   * @throws ApplicationException
   * @see com.dcivision.workflow.bean.MtmWorkflowStepWorkflowStep
   */
  public void insertStepRelation(List workflowStepList,List sortWorkflowStepList,Integer rootID){
      for (int i=0;i<workflowStepList.size();i++){
          MtmWorkflowStepWorkflowStep tempStepStep = (MtmWorkflowStepWorkflowStep)workflowStepList.get(i);
          boolean bInserted = false;
          if (tempStepStep.getParentStepID().equals(rootID)){
              for (int j=0;j<sortWorkflowStepList.size();j++){
                  MtmWorkflowStepWorkflowStep insertedStepStep = (MtmWorkflowStepWorkflowStep)sortWorkflowStepList.get(j);
                  if (insertedStepStep.getID().equals(tempStepStep.getID())){
                      bInserted =true;
                      break;
                  }
              }
              if (bInserted == false){
                  sortWorkflowStepList.add(tempStepStep);
                  insertStepRelation(workflowStepList,sortWorkflowStepList,tempStepStep.getChildStepID());
              }
          }
      }

  }

  /**
   * Checks if the next step due date(s) are correctly assigned.
   * 
   * @param workflowRecordID      The workflow record ID
   * @param currentStepID         The current step ID
   * @param nextStepDueDates      Next step due dates
   * @param boolean
   * @throws ApplicationException If due date is not assigned (when it is mandatory)
   *                              or wrongly assigned (for examples, assign a due 
   *                              date that is earlier than today.
   */
  public void checkNextStepDueDates(
        Integer workflowRecordID,
        Integer currentStepID,
        String nextStepDueDates,
        boolean isStartStep)
    throws ApplicationException {
    MtmWorkflowStepWorkflowStepDAObject stepStepDAO = new MtmWorkflowStepWorkflowStepDAObject(this.sessionCon,this.dbConn);
    WorkflowStepDAObject wfStepDAO = new WorkflowStepDAObject(this.sessionCon,this.dbConn);
    String[] dueDateArr = null;
    int arrIndex = 0;

    //check mandatory dynamic assign due date
    if(isStartStep){
      WorkflowStep wfStep = (WorkflowStep)wfStepDAO.getSubmitStepByWorkflowRecordID(workflowRecordID);
      currentStepID = wfStep.getID();
    }

    if(!Utility.isEmpty(nextStepDueDates)){
      dueDateArr = TextUtility.splitString(nextStepDueDates,";");
    }

    List childStepList = stepStepDAO.getListByParentStepID(currentStepID);
    for(int i=0; i<childStepList.size(); i++ ){
      MtmWorkflowStepWorkflowStep stepStep = (MtmWorkflowStepWorkflowStep)childStepList.get(i);
      WorkflowStep tmpStep = (WorkflowStep)wfStepDAO.getObjectByID(stepStep.getChildStepID());
      if(WorkflowStep.DYNAMIC_ASSIGN_DUE_DATE_TRUE.equals(tmpStep.getAllowAssignDueDate()) ||
         WorkflowStep.DYNAMIC_ASSIGN_DUE_DATE_MANDATORY.equals(tmpStep.getAllowAssignDueDate()) ){

        if(Utility.isEmpty(dueDateArr) || Utility.isEmpty(dueDateArr[arrIndex])){
          throw new ApplicationException(ErrorConstant.WORKFLOW_NEXT_STEP_DUE_DATES_REQUIRED,
                new ApplicationException(),tmpStep.getStepName());
        }

        if (!Utility.isEmpty(dueDateArr[arrIndex]) &&
            Utility.timestampToCalendar(TextUtility.parseDBDateTimeToTimeStamp(dueDateArr[arrIndex]) ).before(Utility.timestampToCalendar(Utility.getCurrentTimestamp())) ){
          throw new ApplicationException(ErrorConstant.WORKFLOW_DUE_DATE_CANNOT_BE_LESS_THAN_CURRENT_DATE);
        }

        arrIndex++;
      }

    }

  }

  /**
   * Checks if the due dates of second steps of the workflow are correctly assigned
   * 
   * @param workflowRecordID      The workflow record ID
   * @param nextStepDueDates      Next step due dates
   * @throws ApplicationException If due date is not assigned (when it is mandatory)
   *                              or wrongly assigned (for examples, assign a due 
   *                              date that is earlier than today.
   */
  public void checkSecondStepDueDates(
      Integer workflowRecordID,
      String nextStepDueDates)
  throws ApplicationException {
    this.checkNextStepDueDates(workflowRecordID, null, nextStepDueDates, true);
  }

  /**
   * Checks if the next step due date(s) are correctly assigned.
   * 
   * @param workflowRecordID      The workflow record ID
   * @param currentStepID         The current step ID
   * @param nextStepDueDates      Next step due dates
   * @throws ApplicationException If due date is not assigned (when it is mandatory)
   *                              or wrongly assigned (for examples, assign a due 
   *                              date that is earlier than today.
   */
  public void checkNextStepDueDates(
      Integer workflowRecordID,
      Integer currentStepID,
      String nextStepDueDates)
  throws ApplicationException {
    this.checkNextStepDueDates(workflowRecordID,currentStepID,nextStepDueDates,false);
  }
  
  //added by nancy
  /**
   * Delete record and message by recordID
   * 
   * @param recordID The workflow record ID
   * @throws ApplicationException
   */
  public void deleteStepByRecordID(Integer recordID) throws ApplicationException{
  	WorkflowStepDAObject wfStepDAO = new WorkflowStepDAObject(this.sessionCon,this.dbConn);    
  	
  	List tempStep;
  	//get all step
  	tempStep = wfStepDAO.getListByWorkflowRecordID(recordID);
  	for(int j=0;j<tempStep.size();j++){
  		WorkflowStep tmpWorkflowStep = (WorkflowStep)tempStep.get(j);
  		
  		//get parameters and delete(workflow_step_parameter_value)
  		this.deleteStepParametersByStepID(tmpWorkflowStep.getID());
  		
  		//delete step(workflow_step)
  		wfStepDAO.deleteObject(tmpWorkflowStep);
  		
  		//delete(workflow_step_route)
  		this.deleteStepRouteByStepID(tmpWorkflowStep.getID());
  		
  		//delete(workflow_step_form_equat)
  		this.deleteStepFormEquatByStepID(tmpWorkflowStep.getID());
  		
  		//mtm_wf_step_user_actor
  		this.deleteStepUserActorByStepID(tmpWorkflowStep.getID());
  		
  		//mtm_wf_step_priority_rule
  		this.deleteStepPriorityRuleByStepID(tmpWorkflowStep.getID());
  		
  		//mtm_wf_step_notify_rule
  		this.deleteStepNotificationRuleByStepID(tmpWorkflowStep.getID());
  		
  		//mtm_wf_step_form_record
  		this.deleteStepFormRecordByStepID(tmpWorkflowStep.getID());
  	}
  	//delete(mtm_wf_step_wf_step)
  	this.deleteStepStepByRecordID(recordID);
  	
  	//mtm_wf_record_object_link
  	this.deleteStepRecordObjectLinkByRecordID(recordID);
  	
  	//mtm_wf_interrupt_user_actor
  	this.deleteWFInterruptUserActorByRecordID(recordID);
  }
  
  /**
   * Delete record(mtm_wf_interrupt_user_actor) by workflow_record_ID
   * 
   * @param recordID The workflow record ID
   * @throws ApplicationException
   */
  public void deleteWFInterruptUserActorByRecordID(Integer recordID) throws ApplicationException{
  	MtmWorkflowInterruptUserActorDAObject wfInterruptUserAcortDAO = new MtmWorkflowInterruptUserActorDAObject(this.sessionCon,this.dbConn);
  	List tempList = wfInterruptUserAcortDAO.getListByWorkflowRecordID(recordID);
  	for(int i=0;i<tempList.size();i++){
  		MtmWorkflowInterruptUserActor tmpParamet = (MtmWorkflowInterruptUserActor)tempList.get(i);
  		wfInterruptUserAcortDAO.deleteObject(tmpParamet);
  	}
  }
  
  /**
   * Delete Parameters by stepID
   * 
   * @param stepID The workflow step ID
   * @throws ApplicationException
   */
  public void deleteStepParametersByStepID(Integer StepID) throws ApplicationException{
  	WorkflowStepParameterValueDAObject wfParameterValueDAO=new WorkflowStepParameterValueDAObject(this.sessionCon,this.dbConn);
  	List valueList=wfParameterValueDAO.getListByStepID(StepID);
  	for(int i=0;i<valueList.size();i++){
  		WorkflowStepParameterValue tmpParamet = (WorkflowStepParameterValue)valueList.get(i);
  		wfParameterValueDAO.deleteObject(tmpParamet);
  	}
  }
  
  /**
   * Delete record(mtm_wf_step_wf_step) by workflow_record_ID
   * 
   * @param RecordID The workflow record ID
   * @throws ApplicationException
   */
  public void deleteStepStepByRecordID(Integer RecordID) throws ApplicationException{
  	MtmWorkflowStepWorkflowStepDAObject wswsDAO=new MtmWorkflowStepWorkflowStepDAObject(this.sessionCon,this.dbConn);
  	List wswsList = wswsDAO.getListByWorkflowID(RecordID);
  	for(int i=0;i<wswsList.size();i++){
  		MtmWorkflowStepWorkflowStep temp=(MtmWorkflowStepWorkflowStep)wswsList.get(i);
  		wswsDAO.deleteObject(temp);
  	}
  }
  
  /**
   * Delete route by stepID
   * 
   * @param stepID The workflow step ID
   * @throws ApplicationException
   */
  public void deleteStepRouteByStepID(Integer StepID) throws ApplicationException{
  	WorkflowStepRouteDAObject routeDAO=new WorkflowStepRouteDAObject(this.sessionCon,this.dbConn);
  	List routeList=routeDAO.getListByWorkflowStepID(StepID);
  	for(int i=0;i<routeList.size();i++){
  		WorkflowStepRoute tmpParamet = (WorkflowStepRoute)routeList.get(i);
  		routeDAO.deleteObject(tmpParamet);
  	}
  }
  
  /**
   * Delete step form equat by stepID
   * 
   * @param stepID The workflow step ID
   * @throws ApplicationException
   */
  public void deleteStepFormEquatByStepID(Integer StepID) throws ApplicationException{
  	WorkflowStepFormEquatDAObject wsFormEquatDAO=new WorkflowStepFormEquatDAObject(this.sessionCon,this.dbConn);
  	List formEquatList=wsFormEquatDAO.getListByWorkflowStepID(StepID);
  	for(int i=0;i<formEquatList.size();i++){
  		WorkflowStepFormEquat tmpParamet = (WorkflowStepFormEquat)formEquatList.get(i);
  		wsFormEquatDAO.deleteObject(tmpParamet);
  	}
  }
  
  /**
   * Delete record(mtm_wf_step_user_actor) by workflow_step_ID
   * 
   * @param stepID The workflow step ID
   * @throws ApplicationException
   */
  public void deleteStepUserActorByStepID(Integer StepID) throws ApplicationException{
  	MtmWorkflowStepUserActorDAObject mtmWsUserActorDAO=new MtmWorkflowStepUserActorDAObject(this.sessionCon,this.dbConn);
  	List wsUserActorList=mtmWsUserActorDAO.getListByWorkflowStepID(StepID);
  	for(int i=0;i<wsUserActorList.size();i++){
  		MtmWorkflowStepUserActor tmpParamet = (MtmWorkflowStepUserActor)wsUserActorList.get(i);
  		mtmWsUserActorDAO.deleteObject(tmpParamet);
  	}
  }
  
  /**
   * Delete record(mtm_wf_step_priority_rule) by workflow_step_ID
   * 
   * @param stepID The workflow step ID
   * @throws ApplicationException
   */
  public void deleteStepPriorityRuleByStepID(Integer StepID) throws ApplicationException{
  	MtmWorkflowStepPriorityRuleDAObject wsPriorityRuleDAO=new MtmWorkflowStepPriorityRuleDAObject(this.sessionCon,this.dbConn);
  	List wsPriorityRuleList=wsPriorityRuleDAO.getListByWorkflowStepID(StepID);
  	for(int i=0;i<wsPriorityRuleList.size();i++){
  		MtmWorkflowStepPriorityRule tmpParamet = (MtmWorkflowStepPriorityRule)wsPriorityRuleList.get(i);
  		wsPriorityRuleDAO.deleteObject(tmpParamet);
  	}
  }
  
  /**
   * Delete record(mtm_wf_step_notify_target) by workflow_step_ID
   * 
   * @param NotifyRuleID The workflow notify rule ID
   * @throws ApplicationException
   */
  public void deleteStepNotificationTargetByNotifyRuleID(Integer NotifyRuleID) throws ApplicationException{
  	MtmWfStepNotificationTargetDAObject wsNotifyTargetDAO=new MtmWfStepNotificationTargetDAObject(this.sessionCon,this.dbConn);
  	List wsNotifyTarget = wsNotifyTargetDAO.getListByNotifyRuleID(NotifyRuleID);
  	for(int t=0;t<wsNotifyTarget.size();t++){
  		MtmWfStepNotificationTarget tmpNotifyTarget = (MtmWfStepNotificationTarget)wsNotifyTarget.get(t);
  		wsNotifyTargetDAO.deleteObject(tmpNotifyTarget);
  	}
  }
  
  /**
   * Delete record(mtm_wf_step_notify_rule) by workflow_step_ID
   * 
   * @param stepID The workflow step ID
   * @throws ApplicationException
   */
  public void deleteStepNotificationRuleByStepID(Integer StepID) throws ApplicationException{
  	MtmWfStepNotificationRuleDAObject wsNotifyRuleDAO=new MtmWfStepNotificationRuleDAObject(this.sessionCon,this.dbConn);
  	List wsNotyfyRule=wsNotifyRuleDAO.getListByWorkflowStepID(StepID);
  	for(int i=0;i<wsNotyfyRule.size();i++){
  		MtmWfStepNotificationRule tmpParamet = (MtmWfStepNotificationRule)wsNotyfyRule.get(i);
  		//mtm_wf_step_notify_target
  		this.deleteStepNotificationTargetByNotifyRuleID(tmpParamet.getID());
  		wsNotifyRuleDAO.deleteObject(tmpParamet);
  	}
  }
  
  /**
   * Delete record(mtm_wf_step_form_record) by workflow_step_ID
   * 
   * @param stepID The workflow step ID
   * @throws ApplicationException
   */
  public void deleteStepFormRecordByStepID(Integer StepID) throws ApplicationException{
  	MtmWfStepFormRecordDAObject wsFormRceordDAO=new MtmWfStepFormRecordDAObject(this.sessionCon,this.dbConn);
  	List wsFormRecordList=wsFormRceordDAO.getListByWorkflowStepID(StepID);
  	for(int i=0;i<wsFormRecordList.size();i++){
  		MtmWfStepFormRecord tmpParamet = (MtmWfStepFormRecord)wsFormRecordList.get(i);
  		wsFormRceordDAO.deleteObject(tmpParamet);
  	}
  }
  
  /**
   * Delete record(mtm_wf_record_object_link) by workflow_record_ID
   * 
   * @param recordID The workflow record ID
   * @throws ApplicationException
   */
  public void deleteStepRecordObjectLinkByRecordID(Integer recordID) throws ApplicationException{
  	MtmWorkflowRecordObjectLinkDAObject wrObjectLinkDAO=new MtmWorkflowRecordObjectLinkDAObject(this.sessionCon,this.dbConn);
  	List wrObjectLinkList=wrObjectLinkDAO.getListByWorkflowRecordID(recordID);
  	for(int i=0;i<wrObjectLinkList.size();i++){
  		MtmWorkflowRecordObjectLink tmpParamet = (MtmWorkflowRecordObjectLink)wrObjectLinkList.get(i);
  		wrObjectLinkDAO.deleteObject(tmpParamet);
  	}
  }
  
  //end
  public String[][] retrieveWorkflowStepTypes(String categoryID) throws ApplicationException {
    List workflowStepTypesList = new ArrayList();
    workflowStepTypesList.add(new String[]{"workflow.label.step_type_A", WorkflowStep.ACTION_TYPE_APPROVAL});//Approval Task
    workflowStepTypesList.add(new String[]{"workflow.label.step_type_T", WorkflowStep.ACTION_TYPE_TASK_TO_DO});//To Do Task
    workflowStepTypesList.add(new String[]{"workflow.label.step_type_B", WorkflowStep.ACTION_TYPE_BOOLEAN});//Yes/No Task
    workflowStepTypesList.add(new String[]{"workflow.label.step_type_U", WorkflowStep.ACTION_TYPE_USER_DEFINED_TASK});//User Defined Task
    try{
      
      WorkflowRecordDAObject workflowRecordDAO = new WorkflowRecordDAObject(this.sessionCon,this.dbConn);
      WorkflowActionDAObject workflowActionDAO = new WorkflowActionDAObject(this.sessionCon,this.dbConn);

      //WorkflowRecord workflowRecord = (WorkflowRecord)workflowRecordDAO.getObjectByID(TextUtility.parseIntegerObj(maintForm.getWorkflowRecordID()));//simon_del


      //check if the workflow category of the workflow record is ParaForm related.
      //if(SystemWorkflowConstant.FMB_SUBMISSION_BY_FORM.equals(workflowRecord.getWorkflowCategoryID().toString() )){//simon_del
      if(!Utility.isEmpty(categoryID)) {   // falcon_add EIP-216
        if(SystemWorkflowConstant.FMB_SUBMISSION_BY_FORM.equals(categoryID)){//simon_add
          workflowStepTypesList.add(new String[]{"workflow.label.step_type_F", WorkflowStep.ACTION_TYPE_FORM_DRIVEN});//Form Value Driven Task
        }
      }

      workflowStepTypesList.add(new String[]{"workflow.label.type_separator", ""});

      //List workflowActionList = workflowActionDAO.getListByWorkflowCategoryID(workflowRecord.getWorkflowCategoryID());//simon_del
      List workflowActionList = workflowActionDAO.getListByWorkflowCategoryID(TextUtility.parseIntegerObj(categoryID));//simon_add
      for (int i=0; i< workflowActionList.size(); i++) {
        WorkflowAction workflowAction = (WorkflowAction) workflowActionList.get(i);
        //sliever.hu.add
        if(!workflowAction.getActionClassName().equals("com.dcivision.workflow.action.AutoRollbackPreStep")){
        workflowStepTypesList.add(new String[]{workflowAction.getActionLabel(), WorkflowStep.ACTION_TYPE_SYSTEM_AUTO + workflowAction.getID().toString()});
        }
      }
      
      String[][] aWorkflowStepTypes = new String[workflowStepTypesList.size()+1][];
      aWorkflowStepTypes[0]=new String[]{MessageResourcesFactory.getMessage(this.sessionCon.getSessionLocale(), "common.options.select_menu.select_one"), ""};
      for (int i=1; i<=workflowStepTypesList.size(); i++) {
        String [] types = (String[]) workflowStepTypesList.get(i-1);
        types[0]=getLableMessage(this.sessionCon, types[0]);
        aWorkflowStepTypes[i]=types;
      }
      return aWorkflowStepTypes;
      
    } catch (ApplicationException appEx) {
      throw appEx;
    } catch (Exception e) {
      throw new ApplicationException(ErrorConstant.COMMON_UNKNOWN_DAO, e);
    } finally {
       //empty  
    }
  }

  private String getLableMessage(SessionContainer sessionContainer, String lable) throws NumberFormatException {
    String lableMessage ="";
    lableMessage=MessageResourcesFactory.getMessage(sessionContainer.getSessionLocale(), lable);
    if(lableMessage.matches("\\?\\?\\?.+\\?\\?\\?"))//Struts1.1.org.apache.struts.util.PropertyMessageResources.getMessage:"???" + messageKey(locale, key) + "???"
      lableMessage = lable;
    return lableMessage;
  }

}